package org.kungfu.generator;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

import org.kungfu.core.Constants;

import com.jfinal.kit.LogKit;
import com.jfinal.kit.StrKit;

/**
 * Routes 文件生成器
 */
public class RoutesGenerator {
	protected String importModelTemplate =
			"import %s.%s.%sController;%n";
	protected String importTemplate =
			"%nimport com.jfinal.config.Routes;%n%n";
			//"%nimport %s.IndexController;%n%n";
	protected String packageTemplate =
		"package %s.routes;%n%n";
	protected String classDefineTemplate =
		"/**%n" +
		" * Generated by Robot on " + Constants.DATE_TIME + ", do not modify this file.%n" +
		" */%n" +
		"public class %s extends Routes {%n%n";
	protected String configMethodDefineTemplate =
			"\tpublic void config() {%n" ; 
			//"\t\tadd(\"/\", IndexController.class, \"/module\");%n";;
	protected String configMethodContentTemplate =
				"\t\tadd(\"/%s\", %sController.class, \"/views/%s\");%n";
	
	protected String routesPackageName;
	protected String routesOutputDir;
	protected String routesClassName = "RestRoutes";
	protected String modelPackageName;
	
	public RoutesGenerator(String routesPackageName, String routesOutputDir, String modelPackageName) {
		this.routesPackageName = routesPackageName;
		this.routesOutputDir = routesOutputDir;
		this.modelPackageName = modelPackageName;
	}
	
	public void setRoutesOutputDir(String routesOutputDir) {
		if (StrKit.notBlank(routesOutputDir))
			this.routesOutputDir = routesOutputDir;
	}
	
	public void setRoutesPackageName(String routesPackageName) {
		if (StrKit.notBlank(routesPackageName))
			this.routesPackageName = routesPackageName;
	}
	
	public void setRoutesClassName(String routesClassName) {
		if (StrKit.notBlank(routesClassName))
			this.routesClassName = StrKit.firstCharToUpperCase(routesClassName);
	}
	
	public void setModelPackageName(String modelPackageName) {
		if (StrKit.notBlank(modelPackageName))
			this.modelPackageName = modelPackageName;
	}
	
	public void generate(List<TableMeta> tableMetas) {
		System.out.println("Generate Routes file ...");
		StringBuilder ret = new StringBuilder();
		genPackage(ret);
		for (TableMeta tableMeta : tableMetas) 
			genModelImport(tableMeta, ret);
		genImport(ret);
		genClassDefine(ret);
		genMappingMethod(tableMetas, ret);
		ret.append(String.format("}%n%n"));
		wirtToFile(ret);
	}
	
	protected void genModelImport(TableMeta tableMeta, StringBuilder ret) {
		ret.append(String.format(importModelTemplate, modelPackageName, tableMeta.modelName.toLowerCase().replaceAll("_", ""), tableMeta.modelName));
	}
	
	protected void genPackage(StringBuilder ret) {
		ret.append(String.format(packageTemplate, routesPackageName.substring(0, routesPackageName.lastIndexOf('.'))));
	}
	
	protected void genImport(StringBuilder ret) {
		ret.append(String.format(importTemplate, routesPackageName));
	}
	
	protected void genClassDefine(StringBuilder ret) {
		ret.append(String.format(classDefineTemplate, routesClassName));
	}
	
	protected void genMappingMethod(List<TableMeta> tableMetas, StringBuilder ret) {
		ret.append(String.format(configMethodDefineTemplate));
		for (TableMeta tableMeta : tableMetas) {
			String add = String.format(configMethodContentTemplate, tableMeta.modelName.toLowerCase(), tableMeta.modelName, tableMeta.modelName.toLowerCase());
			ret.append(add);
		}
		ret.append(String.format("\t}%n"));
	}
	
	/**
	 * RestRoutes.java 覆盖写入
	 */
	protected void wirtToFile(StringBuilder ret) {
		FileWriter fw = null;
		try {
			File dir = new File(routesOutputDir.substring(0, routesOutputDir.lastIndexOf('/')) + File.separator + "routes" );
			if (!dir.exists())
				dir.mkdirs();
			
			String target = routesOutputDir.substring(0, routesOutputDir.lastIndexOf('/')) + File.separator + "routes" + File.separator + routesClassName + ".java";
			
			File file = new File(target);
			if (file.exists()) {
				return ;	// 若 Model 存在，不覆盖
			}
			
			fw = new FileWriter(target);
			fw.write(ret.toString());
		}
		catch (IOException e) {
			throw new RuntimeException(e);
		}
		finally {
			if (fw != null)
				try {fw.close();} catch (IOException e) {LogKit.error(e.getMessage(), e);}
		}
	}
}




